﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Simple.Utils;
using Simple.Wechat.Models;
using SKIT.FlurlHttpClient.Wechat.Api.Models;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.Work;
using SKIT.FlurlHttpClient.Wechat.Work.Models;

namespace Simple.Wechat
{
    /// <summary>
    /// 企业微信相关接口
    /// </summary>
    public class WechatWork : IDisposable
    {
        public WechatWorkClientOptions clientOptions { get; }

        public WechatWorkClient WorkClient { get; }

        private static object lockobj = new object();

        private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
        private WxAccessToken wxAccessToken = new WxAccessToken();
        private Timer timer;

        public WechatWork(WechatWorkClientOptions clientOptions)
        {
            this.clientOptions = clientOptions;
            this.WorkClient = new WechatWorkClient(clientOptions);
            //立即执行，每7000秒执行一次刷新事件
            timer = new Timer(new TimerCallback(RefreshAccessTokenAsync), null, 0, 7000 * 1000);
        }

        public bool VerifyEventSignature(string signature, string timestamp, string nonce, string echostr)
        {
            var response = WorkClient.VerifyEventSignatureForEcho(signature, timestamp, nonce, echostr, out string replyEcho);
            if (response.Result) return true;

            throw new CustomException($"调用企业微信支付WechatWork验证参数时异常,HResult<{response.Error.HResult}>,ErrorMessage<{response.Error.Message}>", "调用企业微信接口出现异常");
        }

        private async void RefreshAccessTokenAsync(object state)
        {
            if (wxAccessToken.IsExpire)
            {
                await semaphoreSlim.WaitAsync();
                try
                {
                    if (wxAccessToken.IsExpire)
                    {
                        Console.WriteLine($"{DateTime.Now}:执行了WxAccessToken刷新");
                        var request = new CgibinGetTokenRequest()
                        {
                        };

                        var response = await WorkClient.ExecuteCgibinGetTokenAsync(request);
                        if (response.IsSuccessful())
                        {
                            wxAccessToken.AccessToken = response.AccessToken;
                            wxAccessToken.ExpiresIn = response.ExpiresIn;
                            wxAccessToken.TokenExpireTime = DateTime.Now.AddSeconds(response.ExpiresIn);
                        }
                    }
                }
                finally
                {
                    semaphoreSlim.Release();
                }
            }
        }

        /// <summary>微信apitoken</summary>
        public WxAccessToken CgibinTokenAccess
        {
            get
            {
                if (wxAccessToken.IsExpire)
                {
                    RefreshAccessTokenAsync(null);
                    Thread.Sleep(1000);
                }
                return wxAccessToken;
            }
        }

        private T CheckResponse<T>(T response) where T : WechatWorkResponse
        {
            if (response == null || !response.IsSuccessful())
            {
                throw new CustomException($"调用企业微信接口获取返回值{response}时异常,ErrCode<{response?.ErrorCode}>,ErrorMessage<{response?.ErrorMessage}>", "调用企业微信接口异常");
            }
            return response;
        }

        public async Task<CgibinDepartmentCreateResponse> DepartmentCreateAsync(CgibinDepartmentCreateRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinDepartmentCreateAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinDepartmentDeleteResponse> DepartmentDeleteAsync(CgibinDepartmentDeleteRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinDepartmentDeleteAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinDepartmentUpdateResponse> DepartmentUpdateAsync(CgibinDepartmentUpdateRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinDepartmentUpdateAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinUserCreateResponse> UserCreateAsync(CgibinUserCreateRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinUserCreateAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinUserDeleteResponse> UserDeleteAsync(CgibinUserDeleteRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinUserDeleteAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinUserUpdateResponse> UserUpdateAsync(CgibinUserUpdateRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinUserUpdateAsync(request);
            return CheckResponse(response);
        }

        public async Task<CgibinMessageSendResponse> MessageSendAsync(CgibinMessageSendRequest request)
        {
            request.AccessToken = CgibinTokenAccess.AccessToken;
            var response = await WorkClient.ExecuteCgibinMessageSendAsync(request);
            return CheckResponse(response);
        }

        public void Dispose()
        {
            timer.Dispose();
        }
    }
}